package com.cxyd.modules.wms.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cxyd.common.constant.enums.wms.*;
import com.cxyd.common.exception.RootException;
import com.cxyd.modules.wms.dao.*;
import com.cxyd.modules.wms.entity.*;
import com.cxyd.modules.wms.service.AllotExecService;
import com.cxyd.modules.wms.service.CommonService;
import com.cxyd.modules.wms.service.LogWorkService;
import com.cxyd.modules.wms.service.PostWcsService;
import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class AllotExecServiceImpl implements AllotExecService {

    private static final Logger logger = LoggerFactory.getLogger(AllotExecServiceImpl.class);

    private final OrderDetailDao orderDetailDao;
    private final StockDao stockDao;
    private final TaskDao taskDao;
    private final LogWorkService logWorkService;
    private final StationDao stationDao;
    private final PostWcsService postWcsService;
    private final CommonService commonService;
    private final OrderDao orderDao;
    private final PostWcsDao postWcsDao;
    private final LocateDao locateDao;

    public AllotExecServiceImpl(OrderDetailDao orderDetailDao, StockDao stockDao, TaskDao taskDao, LogWorkService logWorkService, StationDao stationDao, PostWcsService postWcsService, CommonService commonService, OrderDao orderDao, PostWcsDao postWcsDao, LocateDao locateDao) {
        this.orderDetailDao = orderDetailDao;
        this.stockDao = stockDao;
        this.taskDao = taskDao;
        this.logWorkService = logWorkService;
        this.stationDao = stationDao;
        this.postWcsService = postWcsService;
        this.commonService = commonService;
        this.orderDao = orderDao;
        this.postWcsDao = postWcsDao;
        this.locateDao = locateDao;
    }


    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void procOrderDetailAllotExec(Map<String, Object> params) {
        Long detailId = Long.parseLong(params.get("detailId").toString());
        Long userId = (Long)params.get("userId");
        Date startDate = new Date();
        String comment = "出库执行";
        String code = "0";
        String msg = "出库执行成功";
        String work = "AllotExecServiceImpl.procOrderDetailAllotExec";
        LogWorkEntity insertLogWork = new LogWorkEntity();
        insertLogWork.setWorkName(comment);
        insertLogWork.setRelateNo(detailId.toString());
        insertLogWork.setWorkProc(work);
        insertLogWork.setCreator(userId);
        insertLogWork.setCreateDate(startDate);
        //校验单据是否存在
        OrderDetailEntity orderDetailEntity = orderDetailDao.selectById(detailId);
        if (ObjectUtils.isEmpty(orderDetailEntity)) {
            throw new RootException("出库明细[" + detailId + "]在表中不存在!");
        }
        if (OrderStatusEnum.OUT_COMPLETE.getCode() == orderDetailEntity.getDetailSt()) {
            throw new RootException("出库明细[" + detailId + "]已执行完成!");
        }
        if (OrderStatusEnum.INITIAL.getCode() == orderDetailEntity.getDetailSt()) {
            throw new RootException("出库明细[" + detailId + "]尚未配货!");
        }
        Long orderId = orderDetailEntity.getOrderId();
        OrderEntity orderEntity = orderDao.selectById(orderId);
        if (ObjectUtils.isEmpty(orderEntity)) {
            throw new RootException("出库主单[" + orderId + "]在表中不存在!");
        }
        if (OrderStatusEnum.OUT_COMPLETE.getCode() == orderEntity.getOrderSt()) {
            throw new RootException("出库主单[" + orderId + "]已执行完成!");
        }
        if (OrderStatusEnum.INITIAL.getCode() == orderEntity.getOrderSt()) {
            throw new RootException("出库明细[" + detailId + "]尚未配货!");
        }
        //查询站台(根据所出货位判断站台-CP=CP_OUT_ST  GJ=GJ_OUT_ST)
        String stationNo = "";

        List<TaskEntity> taskEntities = taskDao.selectList(new QueryWrapper<TaskEntity>()
                .eq("task_sub_type", TaskSubTypeEnum.CHECK.getCode())
                .eq("task_st", TaskStEnum.INITIAL.getCode())
                .eq("detail_id", detailId));
        BigDecimal actQty = BigDecimal.ZERO;
        for (TaskEntity taskEntity : taskEntities) {
            Long stockId = taskEntity.getStockId();
            StockEntity stockEntity = stockDao.selectById(stockId);
            if (ObjectUtils.isEmpty(stockEntity)) {
                code = "1001";
                msg = "出库明细[" + detailId + "]执行失败!未找到库存[" + stockId + "]的数据!";
                logger.info(msg);
                insertLogWork.setWorkCode(code);
                insertLogWork.setWorkMsg(msg);
                logWorkService.logWorkInsert(insertLogWork);
                throw new RootException(msg);
            }
            /*目标托盘如果正在出库中需等待其回库 */
            if (!LocateTypeEnum.HW.getCode().contains(stockEntity.getPositionType())) {
                code = "1001";
                msg = "出库明细[" + detailId + "]所需库存[" + stockId + "]当前位置[" + stockEntity.getCurPosition() + "]不可出库!";
                logger.info(msg);
                insertLogWork.setWorkCode(code);
                insertLogWork.setWorkMsg(msg);
                logWorkService.logWorkInsert(insertLogWork);
                throw new RootException(msg);
            }
            if (StatusEnum.DISABLE.getCode() == stockEntity.getLockSt()) {
                code = "1001";
                msg = "出库明细[" + detailId + "]所需库存[" + stockId + "]被冻结!不可出库!";
                logger.info(msg);
                insertLogWork.setWorkCode(code);
                insertLogWork.setWorkMsg(msg);
                logWorkService.logWorkInsert(insertLogWork);
                throw new RootException(msg);
            }
//            新增逻辑（根据库存的位置信息判断其目标出库站台）
//            if (stockEntity.getCurPosition().contains("HW-01K")){
//                stationNo="CP_OUT_ST";
//            }else{
//                stationNo="GJ_OUT_ST";
//            }
            //分配出库站台
            QueryWrapper<LocateEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().like(LocateEntity::getLocateType, LocateTypeEnum.ST.getCode())
                    .eq(LocateEntity::getLocateSt, LocateStEnum.FREE.getCode())
                    .likeRight(LocateEntity::getLocateNo, "F")
                    .last("limit 1");
            LocateEntity locateEntity = locateDao.selectOne(queryWrapper);

            if (ObjectUtils.isEmpty(locateEntity)) {
                code = "1001";
                msg = "出库明细[" + detailId + "]所需库存[" + stockId + "]当前位置[" + stockEntity.getCurPosition() + "]无可用出库站台!";
                logger.info(msg);
                insertLogWork.setWorkCode(code);
                insertLogWork.setWorkMsg(msg);
                logWorkService.logWorkInsert(insertLogWork);
                throw new RootException(msg);
            }
            stationNo  = locateEntity.getLocateNo();

            /*更新任务 */
            TaskEntity updateTask = new TaskEntity();
            updateTask.setTaskId(taskEntity.getTaskId());
            updateTask.setComments(comment);
            updateTask.setTaskSt(TaskStEnum.PROGRESS.getCode());
            updateTask.setUpdater(userId);
            updateTask.setUpdateDate(startDate);
            updateTask.setToPosition(stationNo);
            try {
                taskDao.updateById(updateTask);
            } catch (Exception e) {
                logger.info("更新任务失败", e);
                code = "1001";
                msg = e.getMessage();
                insertLogWork.setWorkCode(code);
                insertLogWork.setWorkMsg(msg);
                logWorkService.logWorkInsert(insertLogWork);
                throw new RootException("更新任务失败！");
            }
            List<PostWcsEntity> postWcsEntities = postWcsDao.selectList(new QueryWrapper<PostWcsEntity>()
                    .ne("trk_st", PostWcsStEnum.COMPLETE.getCode())
                    .eq("trk_type", "OT")
                    .eq("cont_no", taskEntity.getContNo()));
            //只有当没有出库设备任务 且 托盘不在站台时，才生成出库任务
            if (CollectionUtils.isEmpty(postWcsEntities) && !LocateTypeEnum.ST.getCode().contains(stockEntity.getPositionType())) {
                PostWcsEntity insertPostWcs = new PostWcsEntity();
                insertPostWcs.setContNo(taskEntity.getContNo());
                insertPostWcs.setTrkType(PostWcsTypeEnum.OT.getCode());
                insertPostWcs.setFrmPos(taskEntity.getFromPosition());
                insertPostWcs.setToPos(stationNo);
                insertPostWcs.setCurPos(taskEntity.getCurrentPosition());
                insertPostWcs.setIsFull(PostWcsFullEnum.FULL.getCode());
                insertPostWcs.setCreator(userId);
                insertPostWcs.setCreateDate(startDate);
                insertPostWcs.setUpdater(userId);
                insertPostWcs.setUpdateDate(startDate);
                insertPostWcs.setComments(comment);
                try {
                    postWcsService.postWcsInsert(insertPostWcs);
                } catch (Exception e) {
                    logger.info("生成搬运任务失败", e);
                    code = "1001";
                    msg = e.getMessage();
                    insertLogWork.setWorkCode(code);
                    insertLogWork.setWorkMsg(msg);
                    logWorkService.logWorkInsert(insertLogWork);
                    throw new RootException("生成搬运任务失败！");
                }
            }
            actQty = actQty.add(taskEntity.getActlQty());
        }
        /*单据更新(任务需全部处理) */
        OrderDetailEntity updateOrderDetail = new OrderDetailEntity();
        updateOrderDetail.setDetailId(detailId);
        updateOrderDetail.setDetailSt(OrderStatusEnum.OUT_STOCK.getCode());
        updateOrderDetail.setUpdater(userId);
        updateOrderDetail.setUpdateDate(startDate);
        updateOrderDetail.setComments(comment);
        updateOrderDetail.setActlQty(actQty);
        try {
            orderDetailDao.updateById(updateOrderDetail);
        } catch (Exception e) {
            logger.info("出库明细更新失败", e);
            code = "1001";
            msg = e.getMessage();
            insertLogWork.setWorkCode(code);
            insertLogWork.setWorkMsg(msg);
            logWorkService.logWorkInsert(insertLogWork);
            throw new RootException("出库明细更新失败！");
        }
        //修改主单状态
        params.put("orderId", orderEntity.getOrderId());
        params.put("comment", comment);
        params.put("userId", userId);
        try {
            commonService.orderStatus(params);
        } catch (Exception e) {
            logger.info("修改主单失败", e);
            code = "1001";
            msg = e.getMessage();
            insertLogWork.setWorkCode(code);
            insertLogWork.setWorkMsg(msg);
            logWorkService.logWorkInsert(insertLogWork);
            throw new RootException("修改主单失败！");
        }
        //记录日志 proc_wms_log_insert
        insertLogWork.setWorkCode(code);
        insertLogWork.setWorkMsg(msg);
        insertLogWork.setCreator(userId);
        logWorkService.logWorkInsert(insertLogWork);
    }
}
